package com.jinly.ryder.account.web;

import com.alibaba.fastjson.JSON;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.service.CaptchaService;
import com.jinly.ryder.account.config.AuthProperties;
import com.jinly.ryder.account.service.UserAuthService;
import com.jinly.ryder.account.service.UserInfoService;
import com.jinly.ryder.account.service.model.UserInfo;
import com.jinly.ryder.account.web.utils.IpUtil;
import com.jinly.ryder.account.web.utils.TokenUtil;
import com.jinly.ryder.account.web.vo.LoginFormVO;
import com.jinly.ryder.account.web.vo.LoginUserVO;
import com.jinly.ryder.account.web.vo.PwdFormVO;
import com.jinly.ryder.common.auth.LoginContent;
import com.jinly.ryder.common.auth.model.AuthType;
import com.jinly.ryder.common.auth.model.TokenInfo;
import com.jinly.ryder.common.error.SystemErrorType;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequiredArgsConstructor
public class LoginController {

    private final UserInfoService userInfoService;
    private final StringRedisTemplate redisTemplate;
    private final CaptchaService captchaService;
    private final AuthProperties authProperties;
    private final UserAuthService userAuthService;

    @GetMapping("captcha/needCheck")
    public Boolean needCheck(HttpServletRequest request) {
        return needCheckCaptcha(request);
    }

    @PostMapping("login")
    public LoginUserVO login(@RequestBody LoginFormVO loginFormVO, HttpServletRequest request) {
        if (needCheckCaptcha(request)) {
            if (loginFormVO.getCaptcha() == null) throw SystemErrorType.BAD_REQUEST.buildError("验证码错误");
            ResponseModel responseModel = captchaService.verification(loginFormVO.getCaptcha());
            if (responseModel.isError()) throw new RuntimeException("验证码错误");
        }
        UserInfo userInfo = userInfoService.checkUserInfo(loginFormVO.getUsername(), loginFormVO.getPassword());
        if (userInfo == null) {
            setCheckCaptcha(request);
            SystemErrorType.BAD_REQUEST.throwError("账户或者密码错误");
        }
        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtils.copyProperties(userInfo, loginUserVO);
        List<AuthType> userAuthTypeList = userAuthService.getUserAuthTypes(userInfo.getId());
        loginUserVO.setUserAuthTypeList(userAuthTypeList);
        String sessionId = UUID.randomUUID().toString().replaceAll("-", "");
        redisTemplate.opsForValue().set("loginSession:" + sessionId, JSON.toJSONString(loginUserVO), 30, TimeUnit.MINUTES);
        TokenInfo tokenInfo = new TokenInfo(userInfo.getId(), sessionId);
        loginUserVO.setToken(TokenUtil.getToken(authProperties, tokenInfo));
        clearCheckCaptcha(request);
        return loginUserVO;
    }

    public void clearCheckCaptcha(HttpServletRequest request) {
        String ip = IpUtil.getRemoteIp(request);
        redisTemplate.delete("CheckCaptcha_" + ip);
    }

    public void setCheckCaptcha(HttpServletRequest request) {
        String ip = IpUtil.getRemoteIp(request);
        redisTemplate.opsForValue().set("CheckCaptcha_" + ip, ip, 1, TimeUnit.HOURS);
    }

    private boolean needCheckCaptcha(HttpServletRequest request) {
        String ip = IpUtil.getRemoteIp(request);
        return redisTemplate.hasKey("CheckCaptcha_" + ip);
    }

    @GetMapping("logout")
    public void logout() {
        redisTemplate.delete("loginSession:" + LoginContent.getSessionId());
    }

    @GetMapping("getLoginUser")
    public LoginUserVO getLoginUser() {
        String json = redisTemplate.opsForValue().get("loginSession:" + LoginContent.getSessionId());
        if (json == null) {
            SystemErrorType.UNAUTHORIZED.throwError();
        }
        LoginUserVO loginUserVO = JSON.parseObject(json, LoginUserVO.class);
        return loginUserVO;
    }

    @PostMapping("changePwd")
    public void changePwd(@RequestBody PwdFormVO pwdFormVO) {
        UserInfo userInfo = userInfoService.getUserInfo(LoginContent.getUserId());
        if (userInfo != null) {
            if (userInfoService.checkUserInfo(userInfo.getUsername(), pwdFormVO.getOldPwd()) == null) {
                SystemErrorType.BAD_REQUEST.throwError("密码错误");
            }
            userInfo.setPassword(pwdFormVO.getNewPwd());
            userInfoService.updateUserInfo(userInfo);
        }
    }
}
